#!/usr/bin/env python
# coding=utf-8

from vavava.util import _interval_timer
from vavava.basethread import BaseThread
from vavava.workshop import WorkShop
from vavava.workqueue import Work
from select import select
import socket,time


RECV_BUFF_SIZE=1024

class _tran_work(Work):
    def __init__(self,remote=(),log=None):
        Work.__init__(self,log=log)
        self._remote    = remote[0]
        self._addr      = remote[1]
        self._req_data  = None
        self._resp_data = None

    def do(self,worker):
        try:
            data = self._remote.recv(RECV_BUFF_SIZE)
            if data:
                self._req_data = data
                self.handle_request()
                if self._resp_data:
                    self._remote.send(self._resp_data)
            else:
                self.log.warn("transformation error, peer --> [%s]")
        except Exception as e:
            self.log.exception(e)
        finally:
            if self._remote:
                self._remote.close()

    def handle_request(self):
        self.log.info("%r",self._req_data)

class CmdServer(BaseThread):
    def __init__(self,work_type=_tran_work,log=None):
        BaseThread.__init__(self,name="CmdSer",log=log)
        self._sock = None
        self._local_ip = "0.0.0.0"
        self._local_port = 4444
        self._ws = WorkShop(minsize=5,log=log)
        self._work_type = work_type

    def _prepare(self):
        try:
            self._sock = socket.socket()
            self._sock.bind( (self._local_ip, self._local_port) )
            self._sock.listen(5)
            return True
        except Exception as e:
            self.log.exception(e)
            result = False

    def StartServer(self):
        self._ws.StartWork()
        self.running_start()

    def StopServer(self,timeout=33):
        self._ws.StopWork(timeout)
        self.running_stop()
        self.join(timeout)

    def run(self):
        initialised = False
        while self.IsRunning:
            try:
                if not initialised and not self._prepare():
                    bt = _interval_timer()
                    self.log.warn("[%s] Failed on binding server, retry later.", self.getName())
                    interval = _interval_timer() - bt
                    if interval < 1:
                        time.sleep(1-interval)
                    continue
                else:
                    initialised = True
                    inputs=[self._sock]

                rs, ws, es = select( inputs, [], [], 1 )
                if self._sock in rs:
                    remote,remote_addr = self._sock.accept()
                    work = self._work_type((remote,remote_addr), log=self.log)
                    self._ws.QueueWork(work)
            except Exception as e:
                self.log.exception(e)
                self._sock.close()
                initialised=False


def test():
    pass


if __name__ == '__main__':
    import vavava.util
    log = vavava.util.initlog("./log/test_cmd_ser.log")
    ser = CmdServer(log=log)
    try:
        ser.StartServer()
        #test(log)
        while True:
            time.sleep(1)
    except(KeyboardInterrupt):
        log.error('main thread(%f): User canceled by Ctrl-c', _interval_timer())
    except Exception as e:
        log.exception(e)
    finally:
        log.info('main thread(%f):stop', _interval_timer())
        ser.StopServer()
        log.info('main thread(%f):stopped', _interval_timer())